gusucode.com > VC下基于winsock2的原始套接子发送程序源码 > VC下基于winsock2的原始套接子发送程序源码/Copy of RawSocket/RawSocket.cpp
#include <stdio.h> #include <winsock2.h> #include <ws2tcpip.h> // Standard TCP flags #define URG 0x20 #define ACK 0x10 #define PSH 0x08 #define RST 0x04 #define SYN 0x02 #define FIN 0x01 #define SOURCE_PORT 6000 #define MAX_RECEIVEBYTE 255 typedef struct ip_hdr //定义IP首部 { unsigned char h_verlen; //4位首部长度,4位IP版本号 unsigned char tos; //8位服务类型TOS unsigned short total_len; //16位总长度 unsigned short ident; //16位标识 unsigned short frag_and_flags; //3位标识位,13位段偏移 unsigned char ttl; //8位生存时间TTL unsigned char proto; //8位协议(TCP,UDP或其他) unsigned short checksum; //16位IP首部校验和 unsigned int sourceIP; //32位源IP地址 unsigned int destIP; //32目的IP地址 }IPHEADER; typedef struct tsd_hdr //定义TCP伪首部 { unsigned long saddr; //源地址 unsigned long daddr; //目的地址 char mbz; char ptcl; //协议类型 unsigned short tcpl; //TCP长度 }PSDHEADER; typedef struct tcp_hdr //定义TCP首部 { USHORT th_sport; //16位源端口 USHORT th_dport; //16位目的端口 unsigned int th_seq; //32位序列号 unsigned int th_ack; //32位确认号 unsigned char th_lenres; //4位首部长度,6位保留字 unsigned char th_flag; //6位标识位 USHORT th_win; //16位窗口大小 USHORT th_sum; //16位网络校验和 USHORT th_urp; //16位紧急数据偏移量 }TCPHEADER; //CheckSum 计算校验和 USHORT checksum(USHORT *buffer, int size) { //将缓冲区中的数据加起来 //数据(包括IP头和IP数据)在存储区中实际上是以二进制的形式存放的, //所以相当于将这些二进制数据加在一起 unsigned long cksum=0; while(size >1) { cksum+=*buffer++; size -=sizeof(USHORT); } if(size ) { cksum += *(UCHAR*)buffer; } //上面完成了求和运算 //十六位运算有可能而且很有可能产生超过十六位的结果 //回卷 取出高十六位 加上 原来的低十六位 cksum = (cksum >> 16) + (cksum & 0xffff); //再加一次可保证计算值在十六位内 cksum += (cksum >>16); //取反返回即为校验和 return (USHORT)(~cksum); } int main() { //加载启动winsock.dll WSADATA WSAData; if (WSAStartup(MAKEWORD(2,2), &WSAData)!=0) { printf("WSAStartup Error!\n"); return false; } //创建socket SOCKET sock; if ((sock=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,WSA_FLAG_OVERLAPPED))==INVALID_SOCKET) { printf("Socket Setup Error!\n"); return false; } //设置socket选项 BOOL flag; flag=true; if (setsockopt(sock,IPPROTO_IP, IP_HDRINCL,(char *)&flag,sizeof(flag))==SOCKET_ERROR) { //IP_HDRINCL IP头包含 printf("setsockopt IP_HDRINCL error!\n"); return false; } int rect,nTimeOver; nTimeOver=1000; if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&nTimeOver, sizeof(nTimeOver))==SOCKET_ERROR) { printf("setsockopt SO_SNDTIMEO error!\n"); return false; } //地址设置 SOCKADDR_IN addr_in; addr_in.sin_family=AF_INET; addr_in.sin_port=htons(6000); addr_in.sin_addr.S_un.S_addr=inet_addr("219.242.120.133"); IPHEADER ipHeader; TCPHEADER tcpHeader; PSDHEADER psdHeader; //填充IP首部 //version and length //here,sizeof( ipHeader ) is 20 ipHeader.h_verlen=(4<<4 | sizeof(ipHeader)/sizeof(unsigned long)); ipHeader.tos=0; ipHeader.total_len=htons(sizeof(ipHeader)+sizeof(tcpHeader)); ipHeader.ident=1; ipHeader.frag_and_flags=0; ipHeader.ttl=128; //ipHeader.proto=IPPROTO_TCP; ipHeader.proto=IPPROTO_UDP; ipHeader.checksum=0; ipHeader.sourceIP=inet_addr("219.242.120.133"); ipHeader.destIP=inet_addr("219.242.120.134"); //填充TCP首部 tcpHeader.th_dport=htons(6000); tcpHeader.th_sport=htons(SOURCE_PORT); //源端口号 tcpHeader.th_seq=htonl(0x12345678); tcpHeader.th_ack=0; tcpHeader.th_lenres=(sizeof(tcpHeader)/4<<4|0); tcpHeader.th_flag=2; //修改这里来实现不同的标志位探测。2是SYN,1是FIN,16是ACK探测等等 tcpHeader.th_win=htons(512); tcpHeader.th_urp=0; tcpHeader.th_sum=0; psdHeader.saddr=ipHeader.sourceIP; psdHeader.daddr=ipHeader.destIP; psdHeader.mbz=0; psdHeader.ptcl=IPPROTO_TCP; psdHeader.tcpl=htons(sizeof(tcpHeader)); //计算校验和 char szSendBuf[60]={0}; memcpy(szSendBuf, &psdHeader, sizeof(psdHeader)); memcpy(szSendBuf+sizeof(psdHeader), &tcpHeader, sizeof(tcpHeader)); tcpHeader.th_sum=checksum((USHORT *)szSendBuf,sizeof(psdHeader)+sizeof(tcpHeader)); memcpy(szSendBuf, &ipHeader, sizeof(ipHeader)); memcpy(szSendBuf+sizeof(ipHeader), &tcpHeader, sizeof(tcpHeader)); memset(szSendBuf+sizeof(ipHeader)+sizeof(tcpHeader), 0, 4); ipHeader.checksum=checksum((USHORT *)szSendBuf, sizeof(ipHeader)+sizeof(tcpHeader)); memcpy(szSendBuf, &ipHeader, sizeof(ipHeader)); //发送数据通过原始套接字 //此时,我们发送的数据为IP包 //其中的数据就是我们之前填充的TCP头 int i=100; while(i) { //rect = send(sock,szSendBuf,sizeof(ipHeader)+sizeof(tcpHeader),0); rect=sendto(sock, szSendBuf, sizeof(ipHeader)+sizeof(tcpHeader), 0, (SOCKADDR *)&addr_in, sizeof(addr_in)); if (rect==SOCKET_ERROR) { printf("send error!:%d\n",WSAGetLastError()); return false; } else printf("send ok!\n"); i--; } closesocket(sock); WSACleanup(); return 0; }